package com.luo.controller;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.luo.config.Log;
import com.luo.config.LogAspect;
import com.luo.pojo.*;
import com.luo.service.comment.CommentService;
import com.luo.service.content.ContentService;
import com.luo.utils.GeneratorUserAvatarUtil;
import com.luo.utils.RandomFileNameUtil;
import com.luo.utils.RedisUtil;
import com.luo.utils.getPageInfoUtil;
import io.swagger.annotations.ApiOperation;
import org.elasticsearch.rest.RestStatus;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartFile;

import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;
import java.io.*;
import java.util.*;

@RestController
public class ArticleController {
    @Resource
    private ContentService contentService;
    @Resource
    private CommentService commentService;

    @Resource
    private RedisUtil redisUtil;

    protected List<Article> indexArticle;

    private Logger logger = LoggerFactory.getLogger(ArticleController.class);

    @GetMapping({"/", "/index"})
    @ApiOperation("查询主页文章列表") //Operation接口
    public List<Article> recommendArticle(HttpServletRequest request) {
        Object recommend_article = redisUtil.get(RedisCacheEnum.Recommend_Article.getKey());
        if (recommend_article == null){
            List<Article> articleList = contentService.getAllArticle();
            List<Article> published = new ArrayList<>();
            for (Article article1 : articleList) {
                if(article1.getIsPublish()==1){
                    String[] articles = contentService.getArticleTags(article1.getAid());
                    article1.setTags(articles);
                    request.setAttribute("articles", article1);
                    published.add(article1);
                }
            }
            this.indexArticle = published;
            redisUtil.set(RedisCacheEnum.Recommend_Article.getKey(), JSON.toJSONString(indexArticle));
            return this.indexArticle;
        }else{
            String res = recommend_article.toString();
            return JSON.parseArray(res,Article.class);
        }
    }

    @PostMapping("/index")
    @ApiOperation("分页查询后的文章列表  ")
    public List<Article> getLimitArticle(HttpServletRequest request,@RequestBody HashMap<String,String> page){
        this.indexArticle = recommendArticle(request);
        return  new getPageInfoUtil<Article>(page).getPageInfo(page,this.indexArticle);
    }

    @GetMapping("/tags/all")
    public Object getAlltagsAndArticle(HttpServletRequest request) throws JsonProcessingException {
        Object tags1 = redisUtil.get(RedisCacheEnum.Tags.getKey());
        HashMap<String, Object> map = new HashMap<>();
        if (tags1 == null){
            List<String> tags = contentService.queryTag();
            for (String tag : tags) {
                //System.out.println(tag);
                List<Article> articleList = contentService.queryTagArticles(tag);
                for (Article article : articleList) {
                    String[] t = contentService.getArticleTags(article.getAid());
                    article.setTags(t);
                }
                //System.out.println("--------------");
                //System.out.println(articleList);
                List<List<Article>> eachArticle = new ArrayList<>();
                eachArticle.add(articleList);
                map.put(tag, eachArticle);
            }
            map.put("all", tags);
            map.put("AllArticle", recommendArticle(request));
            redisUtil.set(RedisCacheEnum.Tags.getKey(),JSON.toJSONString(map));
            return map;
        }else{
            return JSON.parseObject((String) tags1);
        }
    }

    @GetMapping("/tags/{tagName}")
    public List<Article> getThisTagArticle(HttpServletRequest request, @PathVariable("tagName") String tagName) {
        List<Article> articleList = contentService.queryTagArticles(tagName);
        Object tags = redisUtil.get("Tags:" + tagName);
        if (tags == null){
            for (Article article : articleList) {
                String[] t = contentService.getArticleTags(article.getAid());
                article.setTags(t);
            }
            redisUtil.set("Tags:"+tagName,JSON.toJSONString(articleList));
        }else{
            articleList = JSON.parseArray(redisUtil.get("Tags:"+tagName).toString(),Article.class);
        }
        request.setAttribute("articleList", articleList);
        return articleList;
    }

    @GetMapping("/archives")
    public List<ArticleByDate> getDateArtiles(HttpServletRequest request) {
        //返回一个大集合数组：[{year:'',month:'',articleList:[{},{}]},{year:'',month:'',articleList:[{},{}]}]
        List<ArticleByDate> list = new ArrayList<>();
        Object dateArticles = redisUtil.get(RedisCacheEnum.Date_Articles.getKey());
        if (dateArticles == null){
            String[] strings = contentService.queryDate();
            List<Article> articleList = recommendArticle(request);
            for (String string : strings) {
                ArticleByDate byDate = new ArticleByDate();
                List<Article> mounthArt = new ArrayList<>();
                for (int i = 0; i < articleList.size(); i++) {
                    if (articleList.get(i).getCreated().contains(string)) {
                        byDate.setYear(string.substring(0, 4));
                        byDate.setMonth(string.substring(5, 7));
                        mounthArt.add(articleList.get(i));
                    }
                    byDate.setArticleList(mounthArt);
                }
                list.add(byDate);
            }
            redisUtil.set(RedisCacheEnum.Date_Articles.getKey(),JSON.toJSONString(list));
        }else{
           list=JSON.parseArray(dateArticles.toString(),ArticleByDate.class);
        }
        return list;
    }

    @GetMapping("/categories/all")
    public Object getAllCategoriesArticle(HttpServletRequest request){
        Object o = redisUtil.get(RedisCacheEnum.Categories.getKey());
        if (o == null){
            String[] categories = contentService.queryCategories();
            HashMap<String,Object> map = new HashMap<>();
            for (String category : categories) {
                List<Article> articleList = contentService.queryCateArticles(category);
                for (Article article : articleList) {
                    String[] t = contentService.getArticleTags(article.getAid());
                    article.setTags(t);
                }
                List<List<Article>> eachArticle = new ArrayList<>();
                eachArticle.add(articleList);
                map.put(category, eachArticle);
            };
            map.put("all",categories);
            map.put("AllArticle",recommendArticle(request));
            redisUtil.set(RedisCacheEnum.Categories.getKey(),JSON.toJSONString(map));
            return map;
        }else{
            return o;
        }
    }

    @GetMapping("/categories/{categoryName}")
    public List<Article> getThisCateArticle(HttpServletRequest request,@PathVariable("categoryName")String categoryName){
        String key = RedisCacheEnum.Categories.getKey()+":"+categoryName;
        Object o = redisUtil.get(key);
        if(o==null){
            List<Article> articleList = contentService.queryCateArticles(categoryName);
            for (Article article : articleList) {
                String[] t = contentService.getArticleTags(article.getAid());
                article.setTags(t);
            }
            request.setAttribute("articleList", articleList);
            redisUtil.set(key,JSON.toJSONString(articleList));
            return articleList;
        }else{
            return JSON.parseArray(o.toString(),Article.class);
        }
    }

    @GetMapping("/post/{id}")
    public Article getIdArticle(HttpServletRequest request,@PathVariable("id")int id){
            Article articleById = this.contentService.getArticleById(id);
            articleById.setTags(this.contentService.getArticleTags(id));
            articleById.setCategory(this.contentService.getCategory(id));
            return articleById;
    }

    @PutMapping("/post/agree/{id}/{agreeNumber}")
    public int agreeArticle(HttpServletRequest request,@PathVariable("id")int id,@PathVariable("agreeNumber")int agreeNumber){
        Article article = new Article();
        article.setAid(id);
        article.setAgree(agreeNumber);
        try{
            this.contentService.updateArticleById(article);
            return 1;
        }catch (Exception e){
            e.printStackTrace();
            return 0;
        }
    }

    @PutMapping("/fresh/comment")
    public String changeArticle(HttpServletRequest request){
        List<Article> allArticle = this.contentService.getAllArticle();
        for (Article article : allArticle) {
            int aid = article.getAid();
            int sizeF = this.commentService.getOwnersAllComments("post:" + aid).size();
            int sizeR = this.commentService.queryReplyComments("post:"+aid).size();
            //System.out.println(sizeF+sizeR);
            article.setCommentsNum(sizeF+sizeR);
            this.contentService.updateArticleById(article);
        }
        return "刷新评论数量完毕!";
    }

    @PostMapping("/getTags")
    public List<Tag> getTag(HttpServletRequest request, @RequestBody HashMap<String,String> page){
        List<Tag> strings = this.contentService.selectTagsById();
        try{
            return new getPageInfoUtil<Tag>(page).getPageInfo(page,strings);
        }catch (NumberFormatException e){
         return strings;
        }
    }

    @Log(logStr = "执行删除tag操作")
    @DeleteMapping("/deleteTag/{tid}")
    public int deleteTag(HttpServletRequest request, @PathVariable("tid")int tid){
        contentService.delAboutArticlesCache();
        return this.contentService.deleteTag(tid);
    }

    @Log(logStr = "执行修改tag操作")
    @PutMapping("/updateTag/{tid}/{tag}")
    public int updateTag(@PathVariable("tid")int tid,@PathVariable("tag")String tag){
        contentService.delAboutArticlesCache();
        return this.contentService.updateTag(tid,tag);
    }

    @Log(logStr = "执行新增tag操作")
    @PostMapping("/insertTag/{tag}")
    public int insertTag(@PathVariable("tag")String tag){
        contentService.delAboutArticlesCache();
        return this.contentService.insertTag(tag);
    }

    @GetMapping("/getTags/{tag}")
    public List<Tag> searchTag(@PathVariable("tag")String tag){
        return this.contentService.getTagsByTag(tag);
    }

    @Log(logStr = "执行删除category操作")
    @DeleteMapping("/deleteCate/{cid}")
    public int deleteCate(@PathVariable("cid")int cid){
        contentService.delAboutArticlesCache();
        return this.contentService.deleteCate(cid);
    }

    @Log(logStr = "执行修改category操作")
    @PutMapping("/updateCate/{cid}/{cate}")
    public int updateCate(@PathVariable("cid")int cid,@PathVariable("cate")String cate){
        contentService.delAboutArticlesCache();
        return this.contentService.updateCate(cid,cate);
    }

    @Log(logStr = "执行新增category操作")
    @PostMapping("/insertCate/{cate}")
    public int insertCate(@PathVariable("cate")String cate){
        contentService.delAboutArticlesCache();
        return this.contentService.insertCate(cate);
    }

    @GetMapping("/getCates/{cate}")
    public List<Category> searchCate(@PathVariable("cate")String cate){
        return this.contentService.getCateByCate(cate);
    }

    @PostMapping("/getCate")
    public List<Category> getType(@RequestBody HashMap<String,String> page){
        List<Category> strings = this.contentService.selectCateById();
        try{
            return new getPageInfoUtil<Category>(page).getPageInfo(page,strings);
        }catch (NumberFormatException e){
            return strings;
        }
    }

    @PostMapping("/upload/picture")
    public String uploadImgs(@RequestParam(value = "file",required = false)MultipartFile file) throws IOException {
        final String WIN_UPLOAD_IMGPATH = "E:/project/project_code/luoqianyi_blog/blog-java/src/main/resources/static/pictures/";
        final String LINUX_UPLOAD_IMGPATH = "/project/blog-java/src/main/resources/static/pictures/";
        InputStream in = file.getInputStream();
        File mkdir = null;
        //定义输出流，将文件写入硬盘
        String fileName = RandomFileNameUtil.generateRandomFileName(file.getOriginalFilename());
        if(System.getProperty("os.name").toLowerCase().startsWith("win")){
            mkdir = new File(WIN_UPLOAD_IMGPATH);
        }else{
           mkdir = new File(LINUX_UPLOAD_IMGPATH);
        }
        if(!mkdir.exists()){
            mkdir.mkdirs();
        }
        FileOutputStream os = new FileOutputStream(mkdir.getPath()+"/"+ fileName);
        int len = 0;
        while((len=in.read())!=-1){
            os.write(len);
        }
        os.flush();
        in.close();
        os.close();
        return "/pictures/"+fileName;
    }

    @Log(logStr = "执行新增article操作")
    @PostMapping("/insertArticle")
    public int insertArticle(HttpServletRequest request, @RequestBody HashMap<String,Object> article){
        contentService.delAboutArticlesCache();
        String title = (String) article.get("title");
        int cid = (int)article.get("cid");
        int isPublish = (int)article.get("is_published");
        int readTime = (int)article.get("readTime");
        int recommed = (int)article.get("recommed");
        String content = (String) article.get("content");
        String discribe = article.get("discribe").toString().substring(0,250);
        String tags = (String) article.get("tag_id");
        String[] tagIds = tags.split(",");
        int articleStatus = 0;
        try{
            articleStatus = this.contentService.insertArticle(cid,title,isPublish,readTime,discribe,recommed,content);
        }catch (Exception e){
            return 0;
        }
        int tagStatus = 0;
        if(articleStatus==1){
            int aid = this.contentService.getArticleByTitle(title).getAid();
            if(tags.length()!=0){
                List<ArticleTag> articleTagList = new ArrayList<>();
                for (String tagId : tagIds) {
                    ArticleTag articleTag = new ArticleTag();
                    articleTag.setAid(aid);
                    articleTag.setTid(Integer.parseInt(tagId));
                    articleTagList.add(articleTag);
                }
                tagStatus = this.contentService.bindArticleAndTag(articleTagList);
            }
            Article article1 = this.contentService.getArticleByTitle(title);
            if(article1.getIsPublish()==1) {
                RestStatus restStatus = this.contentService.insertArticleES(article1);
                logger.warn("新增文章插入ElasticSearch："+restStatus);
            }
        }
     return articleStatus + tagStatus;
    }

    @PostMapping("/addViews")
    public String getViews(HttpServletRequest request){
        String route = request.getHeader("route");
//        System.out.println(route);
        return this.contentService.saveViews(route);
    }

    @GetMapping("/search/{keyword}")
    public List<Map<String,Object>> getSearchArticle(@PathVariable("keyword")String keyword){
        return this.contentService.searchArticleByES(keyword);
    }
}
